﻿using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
using XYRenderPipelines.Runtime;

namespace XYRendering.Vegetation
{
    [CustomEditor(typeof(VGInstancingDataRenderer))]
    public class VGInstancingDataRendererEditor : UnityEditor.Editor
    {
        private SerializedProperty _bakeData;
        private SerializedProperty _lodCount;
        private SerializedProperty _maxLodDistance;
        private SerializedProperty _lodDistances;

        private SerializedProperty _showLodBands;
        private SerializedProperty _lodBandsColor;
        
        private SerializedProperty _heightOffset;
        private SerializedProperty _showBounds;
        private SerializedProperty _boundsColor;


        private void OnEnable()
        {
            _bakeData = serializedObject.FindProperty("bakeData");
            _lodCount = serializedObject.FindProperty("lodCount");
            _maxLodDistance = serializedObject.FindProperty("maxLodDistance");
            _lodDistances = serializedObject.FindProperty("lodDistances");
            _showLodBands = serializedObject.FindProperty("showLodBands");
            _lodBandsColor = serializedObject.FindProperty("lodBandsColor");
            _heightOffset = serializedObject.FindProperty("heightOffset");
            _showBounds = serializedObject.FindProperty("showBounds");
            _boundsColor = serializedObject.FindProperty("boundsColor");
        }

        public override void OnInspectorGUI()
        {
            serializedObject.Update();

            EditorGUILayout.PropertyField(_bakeData);
            
            if (!_isXYPipeline)
            {
                EditorGUILayout.HelpBox("当前项目未使用XYRenderPipeline,非兼容的渲染管线 ！", MessageType.Error);
                serializedObject.ApplyModifiedProperties();
                return;
            }

            if (!IsRenderFeatureSetUp())
            {
                EditorGUILayout.HelpBox("XYPipeline工程设置未添加VGInstancingRenderFeature ！", MessageType.Error);
                
                if (GUILayout.Button("添加"))
                    SetUpRenderFeature();
                
                serializedObject.ApplyModifiedProperties();
                return;
            }
            


            if (_bakeData.objectReferenceValue == null)
            {
                EditorGUILayout.HelpBox("请指定烘焙数据", MessageType.Error);
                serializedObject.ApplyModifiedProperties();
                return;
            }

            EditorGUILayout.PropertyField(_lodCount);

            EditorGUI.indentLevel++;
            
            Vector4 lodDistancesVec4 = _lodDistances.vector4Value;
            bool shouldUpdateLodDistances = false;
            
            // Max Lod Distance
            EditorGUI.BeginChangeCheck();
            int x = EditorGUILayout.IntField(new GUIContent(_maxLodDistance.displayName, "超过该距离的Objects将不被渲染"), Mathf.Max(_maxLodDistance.intValue, 50));
            if (EditorGUI.EndChangeCheck())
            {
                _maxLodDistance.intValue = x;
                lodDistancesVec4.w = x;
                shouldUpdateLodDistances = true;
            }
            
            EditorGUI.BeginChangeCheck();
            for (int i = 0; i < _lodCount.intValue; i++)
            {
                float minDistance =  i > 0 ? lodDistancesVec4[i - 1] + 1 : 1;
               
                lodDistancesVec4[i] = EditorGUILayout.IntSlider(new GUIContent("Lod" + i), 
                    (int)Mathf.Clamp(lodDistancesVec4[i], minDistance, _maxLodDistance.intValue),  0, _maxLodDistance.intValue);
                lodDistancesVec4[i] = (int)Mathf.Clamp(lodDistancesVec4[i], minDistance, _maxLodDistance.intValue);
            }

            if(EditorGUI.EndChangeCheck() || shouldUpdateLodDistances)
                _lodDistances.vector4Value = lodDistancesVec4;

            EditorGUI.indentLevel--;


            EditorGUILayout.PropertyField(_heightOffset);

            // debug
            EditorGUILayout.PropertyField(_showLodBands);
            if (_showLodBands.boolValue)
                EditorGUILayout.PropertyField(_lodBandsColor);

            EditorGUILayout.PropertyField(_showBounds);
            if (_showBounds.boolValue)
                EditorGUILayout.PropertyField(_boundsColor);
            
            if (GUILayout.Button("Refresh(调整参数后记得点一下)"))
            {
                VGInstancingDataRenderer realTarget = target as VGInstancingDataRenderer;
                realTarget.Refresh();
            }
            
            
            serializedObject.ApplyModifiedProperties();
        }


        private bool _isXYPipeline => RenderPipelineManager.currentPipeline is  XYRenderPipelines.Runtime.XYRenderPipeline;

        private ScriptableRendererData _rendererData =>
            (GraphicsSettings.currentRenderPipeline as XYRenderPipelineAsset).scriptableRendererData;

        private bool IsRenderFeatureSetUp()
        {
            return _rendererData.rendererFeatures.Exists((rf) => rf is VGInstancingRenderFeature);
        }

        void SetUpRenderFeature()
        {
            var rf = ScriptableObject.CreateInstance<VGInstancingRenderFeature>();
            rf.name = "Draw GPU Instancing Objects";
            
            AssetDatabase.AddObjectToAsset(rf, _rendererData);
            _rendererData.rendererFeatures.Add(rf);
            
            _rendererData.SetDirty(); // For pipeline recreate renderer
            EditorUtility.SetDirty(_rendererData); // for save change to render pipeline asset
            AssetDatabase.SaveAssets();
        }
    }
}